package com.lineage.echo.encryptions;

import com.lineage.server.types.UChar8;
import com.lineage.server.types.ULong32;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Encryption {
  private static final Log _log = LogFactory.getLog(Encryption.class);
  
  private Keys _keys = null;
  
  public void initKeys(long seed) throws Exception {
    try {
      Keys keys = new Keys();
      long[] key = { seed, 2467289058L };
      Blowfish.getSeeds(key);
      keys.DKEY[0] = key[0];
      keys.EKEY[0] = key[0];
      keys.DKEY[1] = key[1];
      keys.EKEY[1] = key[1];
      this._keys = keys;
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
  }
  
  public char[] encrypt(char[] buf) throws Exception {
    try {
      if (this._keys == null)
        throw new Exception(); 
      long mask = ULong32.fromArray(buf);
      _encrypt(buf);
      long[] ekey = this._keys.EKEY;
      int n = 0;
      ekey[0] = ekey[0] ^ mask;
      this._keys.EKEY[1] = ULong32.add(this._keys.EKEY[1], 679411651L);
      return buf;
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
      return null;
    } 
  }
  
  private char[] _encrypt(char[] buf) {
    try {
      int size = buf.length;
      char[] ek = UChar8.fromArray(this._keys.EKEY);
      int n = 0;
      buf[0] = (char)(buf[0] ^ ek[0]);
      int i = 1;
      while (i < size) {
        int n2 = i;
        buf[n2] = (char)(buf[n2] ^ (char)(buf[i - 1] ^ ek[i & 0x7]));
        i++;
      } 
      buf[3] = (char)(buf[3] ^ ek[2]);
      buf[2] = (char)(buf[2] ^ buf[3] ^ ek[3]);
      buf[1] = (char)(buf[1] ^ buf[2] ^ ek[4]);
      buf[0] = (char)(buf[0] ^ buf[1] ^ ek[5]);
      return buf;
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
      return null;
    } 
  }
  
  public byte[] decrypt(byte[] buf) throws Exception {
    try {
      if (this._keys == null)
        throw new Exception(); 
      _decrypt(buf);
      long mask = ULong32.fromArray(buf);
      long[] dkey = this._keys.DKEY;
      int n = 0;
      dkey[0] = dkey[0] ^ mask;
      this._keys.DKEY[1] = ULong32.add(this._keys.DKEY[1], 679411651L);
      return buf;
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
      return null;
    } 
  }
  
  private byte[] _decrypt(byte[] buf) {
    try {
      char[] dk = UChar8.fromArray(this._keys.DKEY);
      byte b3 = buf[3];
      int n = 3;
      buf[3] = (byte)(buf[3] ^ (byte)dk[2]);
      byte b4 = buf[2];
      int n2 = 2;
      buf[2] = (byte)(buf[2] ^ (byte)(b3 ^ dk[3]));
      byte b5 = buf[1];
      int n3 = 1;
      buf[1] = (byte)(buf[1] ^ (byte)(b4 ^ dk[4]));
      byte k = (byte)(buf[0] ^ b5 ^ dk[5]);
      buf[0] = (byte)(k ^ dk[0]);
      int i = 1;
      while (i < buf.length) {
        byte t = buf[i];
        int n4 = i;
        buf[n4] = (byte)(buf[n4] ^ (byte)(dk[i & 0x7] ^ k));
        k = t;
        i++;
      } 
      return buf;
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
      return null;
    } 
  }
}
